package com.qingzhuge.member.utils;

import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import com.google.gson.JsonObject;
import org.apache.http.util.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author : zero.xiao
 * @description : 后台消息推送工具
 * @date :2018/9/30 0030 下午 17:35
 * @since : 1.0.0
 * @modified :
 */
public class MessagePushHelper {
    private static Logger logger = LoggerFactory.getLogger(MessagePushHelper.class);

    private static int mostAliasCount = 1;

    /**
     * 发送通知
     *
     * @param notice    通知内容
     * @param extraData 通知附加的参数
     * @param aliases   用户别名，当别名为NULL或空LIST的时候，发送给所有用户
     * @return 是否发送成功
     */
    public static boolean sendNotice(String appKey,
                                     String appSecret,
                                     String notice,
                                     Map<String, Object> extraData,
                                     List<String> aliases) {
        return sendNoticeMessage(appKey, appSecret, notice, extraData, null, null, aliases);
    }

    /**
     * 发送消息
     *
     * @param message   消息内容
     * @param extraData 消息附加的参数
     * @param aliases   用户别名，当别名为NULL或空LIST的时候，发送给所有用户
     * @return 是否发送成功
     */
    public static boolean sendMessage(String appKey,
                                      String appSecret,
                                      String message,
                                      Map<String, Object> extraData,
                                      List<String> aliases) {
        return sendNoticeMessage(appKey, appSecret, null, null, message, extraData, aliases);
    }

    /**
     * 发送通知，消息
     * 无需发送的内容相应参数为NULL
     *
     * @param notice       通知内容
     * @param extraData    通知附加的参数
     * @param message      消息内容
     * @param extraDataMsg 消息附加的参数
     * @param aliases      用户别名，当别名为NULL或空LIST的时候，发送给所有用户
     * @return 是否发送成功
     */
    private static boolean sendNoticeMessage(String appKey,
                                             String appSecret,
                                             String notice,
                                             Map<String, Object> extraData,
                                             String message,
                                             Map<String, Object> extraDataMsg,
                                             List<String> aliases) {
        JPushClient jpushClient = new JPushClient(appSecret, appKey, null, ClientConfig.getInstance());

        // For push, all you need do is to build PushPayload object.
        List<PushPayload> payloads = buildPushObject(Platform.all(), aliases, notice, extraData, message, extraDataMsg);

        try {
            for (PushPayload payload : payloads) {
                PushResult result = jpushClient.sendPush(payload);
                logger.info("Got result - [{}]", result);
            }
            return true;
        } catch (APIConnectionException e) {
            // Connection error, should retry later
            logger.error("Connection error, should retry later", e);

        } catch (APIRequestException e) {
            // Should review the error, and fix the request
            logger.error("Should review the error, and fix the request", e);
            logger.info("HTTP Status: [{}]", e.getStatus());
            logger.info("Error Code: [{}]", e.getErrorCode());
            logger.info("Error Message: [{}]", e.getErrorMessage());
        }
        return false;
    }

    private static List<PushPayload> buildPushObject(Platform platform,
                                                     List<String> aliases,
                                                     String msgContent,
                                                     Map<String, Object> extraData,
                                                     String msgContentMsg,
                                                     Map<String, Object> extraDataMsg) {
        List<PushPayload> result = new ArrayList<>();
        PushPayload.Builder builder =
                PushPayload.newBuilder().setPlatform(platform);
        if (!TextUtils.isEmpty(msgContent)) {
            IosNotification.Builder iosBuilder = IosNotification.newBuilder()
                    .setAlert(msgContent)
                    .setSound("happy");

            AndroidNotification.Builder androidBuilder = AndroidNotification.newBuilder()
                    .setAlert(msgContent);

            if (extraData != null) {
                for (Map.Entry<String, Object> entry :
                        extraData.entrySet()) {
                    if (entry.getKey() != null && entry.getKey().length() > 0) {
                        if (entry.getValue() instanceof String) {
                            iosBuilder = iosBuilder.addExtra(entry.getKey(), (String) entry.getValue());
                            androidBuilder = androidBuilder.addExtra(entry.getKey(), (String) entry.getValue());
                        }
                        if (entry.getValue() instanceof Number) {
                            iosBuilder = iosBuilder.addExtra(entry.getKey(), (Number) entry.getValue());
                            androidBuilder = androidBuilder.addExtra(entry.getKey(), (Number) entry.getValue());
                        }
                        if (entry.getValue() instanceof Boolean) {
                            iosBuilder = iosBuilder.addExtra(entry.getKey(), (Boolean) entry.getValue());
                            androidBuilder = androidBuilder.addExtra(entry.getKey(), (Boolean) entry.getValue());
                        }
                        if (entry.getValue() instanceof JsonObject) {
                            iosBuilder = iosBuilder.addExtra(entry.getKey(), (JsonObject) entry.getValue());
                            androidBuilder = androidBuilder.addExtra(entry.getKey(), (JsonObject) entry.getValue());
                        }
                    }
                }
            }

            builder = builder.setNotification(Notification.newBuilder()
                    .addPlatformNotification(iosBuilder.build())
                    .addPlatformNotification(androidBuilder.build())
                    .build());
        }

        if (!TextUtils.isEmpty(msgContentMsg)) {
            Message.Builder msgBuilder = Message.newBuilder().setMsgContent(msgContentMsg);
            if (extraDataMsg != null) {
                for (Map.Entry<String, Object> entry :
                        extraDataMsg.entrySet()) {
                    if (entry.getKey() != null && entry.getKey().length() > 0) {
                        if (entry.getValue() instanceof String) {
                            msgBuilder = msgBuilder.addExtra(entry.getKey(), (String) entry.getValue());
                        }
                        if (entry.getValue() instanceof Number) {
                            msgBuilder = msgBuilder.addExtra(entry.getKey(), (Number) entry.getValue());
                        }
                        if (entry.getValue() instanceof Boolean) {
                            msgBuilder = msgBuilder.addExtra(entry.getKey(), (Boolean) entry.getValue());
                        }
                    }
                }
                builder = builder.setMessage(msgBuilder.build());
            }
        }

        builder = builder.setOptions(Options.newBuilder()
                .setApnsProduction(false)
                .build());

        if (aliases == null || aliases.size() == 0) {
            builder = builder.setAudience(Audience.all());
            result.add(builder.build());
        } else {
            for (int i = 0; i < aliases.size(); i += mostAliasCount) {
                List<String> subAliases = aliases.subList(i, Math.min((i + mostAliasCount), aliases.size()));
                PushPayload.Builder builderNew = builder.setAudience(Audience.alias(subAliases));
                result.add(builderNew.build());
            }
        }
        return result;
    }
}
